package com.mocne.TestCases;

import com.google.gson.Gson;
import com.mocne.Common.Excel2Dataprovider;
import com.mocne.Common.PKFTestReport;
import com.mocne.MocneAutoTest.TestCase;
import jxl.read.biff.BiffException;
import org.testng.Assert;
import org.testng.annotations.*;
import redis.clients.jedis.Jedis;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;


@Listeners({PKFTestReport.class})
public class PortTestTestNG_TestCase {

    Jedis jedis = new Jedis("localhost", 6379, 5000, 5000);
    CookieManager cookieManager = new CookieManager();

    @SuppressWarnings("unchecked")
    @Test(dataProvider = "dpData")
    public void interfaceAutoTest(HashMap<String, String> data) {

        String portResult = null;

        if (!data.isEmpty()) {

            TestCase testCase = new TestCase();
            testCase.setProtocol(data.get("Protocol"));
            testCase.setHost(data.get("Host"));
            testCase.setPort(data.get("Port"));
            testCase.setPath(data.get("Path"));
            testCase.setMethod(data.get("Method"));
            testCase.setMethod(data.get("Params"));
            testCase.setHeaders(data.get("Header"));
            testCase.setCheckList(data.get("checkKeys"));
            testCase.setCheckData(data.get("checkValues"));
            testCase.setSetKeys(data.get("setKeys"));
            testCase.setSetValues(data.get("setValues"));
            String real_url;

            Gson gson = new Gson();

            Map<Object, Object> mapSetKeys = new HashMap<>();
            Map<Object, Object> mapSetValues = new HashMap<>();

            if (testCase.getPort().equals("null") || testCase.getPort().isEmpty()) {
                real_url = testCase.getProtocol() + "://" + testCase.getHost() + testCase.getPath();
            } else {
                double finalPort = Double.parseDouble(testCase.getPort());
                real_url = testCase.getProtocol() + "://" + testCase.getHost() + ":" + (int) finalPort + testCase.getPath();
            }

            while (real_url.contains("{{")) {
                String[] aaa = real_url.split("\\{\\{");
                String[] bbb = aaa[1].split("}}");
                String str2 = bbb[0];
                real_url = real_url.replace("{{" + str2 + "}}", jedis.get(str2));
            }
            String params = testCase.getParams();
            while (params.contains("{{")) {
                String[] aaa = params.split("\\{\\{");
                String[] bbb = aaa[1].split("}}");
                String str2 = bbb[0];
                params = params.replace("{{" + str2 + "}}", jedis.get(str2));
                testCase.setParams(params);
            }

            String header = testCase.getHeaders();
            while (header.contains("{{")) {
                String[] aaa = header.split("\\{\\{");
                String[] bbb = aaa[1].split("}}");
                String str2 = bbb[0];
                header = header.replace("{{" + str2 + "}}", jedis.get(str2));
                testCase.setHeaders(header);
            }

            if (testCase.getMethod().equals("GET")) {
                portResult = sendGet(real_url, params, header).substring(4);

                try {
                    Assert.assertNotNull(portResult, "Can not requests the interface! Nothing responded !\n");
                    Assert.assertNotEquals(portResult, "", "Can not requests the interface! Nothing responded !\n");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (testCase.getMethod().equals("POST")) {
                portResult = sendPost(real_url, params, header);

                try {
                    Assert.assertNotNull(portResult, "Can not requests the interface! Nothing responded !\n");
                    Assert.assertNotEquals(portResult, "", "Can not requests the interface! Nothing responded !\n");
                    data.put("Response", portResult);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            String checkKeys = testCase.getCheckList();
            String checkValues = testCase.getCheckData();
            if (!checkKeys.isEmpty() && !checkKeys.equals("null")) {
                System.out.println(checkKeys + checkValues);
                String[] mapCheckKeys = checkKeys.replace("\"", "").split(",");
                String[] mapCheckValues = checkValues.replace("\"", "").split(",");
                for (int i = 0; i < mapCheckKeys.length; i++) {
                    if (mapCheckKeys[i].startsWith("jsonData")) {
                        String[] checks = mapCheckKeys[i].split("\\.");
                        Map<String, Object> map = new HashMap<>();
                        map = gson.fromJson(portResult, map.getClass());
                        Object finalResult = map;
                        for (String tobeCheck :
                                checks) {
                            if (!tobeCheck.equals("jsonData")) {
                                if (isNumeric(tobeCheck)) {
                                    List<?> tmp = (List<?>) finalResult;
                                    finalResult = tmp.get(Integer.getInteger(tobeCheck));
                                } else {
                                    finalResult = ((Map<?, ?>) finalResult).get(tobeCheck);
                                }
                            }
                        }
                        System.out.println("xTestDemo");
                    } else {
                        if (mapCheckValues[i].startsWith("SELECT")) {
//                            Connection con = DriverManager.getConnection(“jdbc:mysql://localhost:3306/web08”,”root”,”root”);
//                            Statement stmt = con.createStatement();
                            System.out.println("This is a select SQL.");

                        } else {
                            Assert.assertEquals(mapCheckKeys[i], mapCheckValues[i], "Check fail !");
                        }
                    }
                }
                System.out.println(mapCheckKeys.length + mapCheckValues.length);
                testCase.setCheckList(Arrays.toString(mapCheckKeys));
                testCase.setCheckData(Arrays.toString(mapCheckValues));

            }

            String setKeys = testCase.getSetKeys();
            String setValues = testCase.getSetValues();
            if (!setKeys.equals("") && !setKeys.equals("null")) {
                mapSetKeys = gson.fromJson(setKeys, mapSetKeys.getClass());
                mapSetValues = gson.fromJson(setValues, mapSetValues.getClass());
                System.out.println(setKeys + setValues);
                System.out.println(mapSetKeys.toString() + mapSetValues.toString());
                testCase.setSetKeys(setKeys);
                testCase.setSetValues(setValues);
            }
        }
    }


    @BeforeMethod
    public void beforeMethod() {
    }

    @AfterMethod
    public void afterMethod() {
    }

    @DataProvider(name = "dpData")
    public Object[][] CasesDataProvider() {
        Object[][] dataProvider = new Object[][]{};

        try {
            String dpFile = jedis.get("dpFile");
            if (!dpFile.isEmpty()) {
                Excel2Dataprovider e = new Excel2Dataprovider(dpFile, jedis.get("caseSheet"));
                dataProvider = e.getExcelData();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dataProvider;
    }


    @SuppressWarnings("unchecked")
    @BeforeClass
    public void beforeClass() throws IOException, BiffException {

        CookieHandler.setDefault(cookieManager);

        Excel2Dataprovider e = new Excel2Dataprovider(jedis.get("dpFile"), "environment");
        Object[][] aimKeyValues = e.getExcelData();
        for (Object[] aimKeyValue :
                aimKeyValues) {
            HashMap<?, ?> aimKey = (HashMap<?, ?>) aimKeyValue[0];
            jedis.set(aimKey.get("key").toString(), aimKey.get("value").toString());
        }

        Excel2Dataprovider loginDatas = new Excel2Dataprovider(jedis.get("dpFile"), "login");
        if (loginDatas.getExcelData() != null) {
            Object[][] loginData = loginDatas.getExcelData();
            Map<String, String> loginMap = (Map<String, String>) loginData[0][0];

            String loginResult;
            if (!loginMap.isEmpty()) {
                TestCase testCase = new TestCase(
                        loginMap.get("Protocol"),
                        loginMap.get("Host"),
                        loginMap.get("Port"),
                        loginMap.get("Path"),
                        loginMap.get("Method"),
                        loginMap.get("Params"),
                        loginMap.get("Header"),
                        "",
                        "",
                        "",
                        ""
                );
                String login_real_url;

                if (testCase.getPort().equals("null") || testCase.getPort().isEmpty()) {
                    login_real_url = testCase.getProtocol() + "://" + testCase.getHost() + testCase.getPath();
                } else {
                    double finalPort = Double.parseDouble(testCase.getPort());
                    login_real_url = testCase.getProtocol() + "://" + testCase.getHost() + ":" + (int) finalPort + testCase.getPath();
                }

                while (login_real_url.contains("{{")) {
                    String[] aaa = login_real_url.split("\\{\\{");
                    String str1 = aaa[0];
                    String[] bbb = aaa[1].split("}}");
                    String str2 = bbb[0];
                    String str3 = bbb[1];
                    login_real_url = str1 + jedis.get(str2) + str3;
                }
                while (testCase.getParams().contains("{{")) {
                    String[] aaa = testCase.getParams().split("\\{\\{");
                    String str1 = aaa[0];
                    String[] bbb = aaa[1].split("}}");
                    String str2 = bbb[0];
                    String str3 = bbb[1];
                    testCase.setParams(str1 + jedis.get(str2) + str3);
                }

                if (testCase.getMethod().equals("GET")) {
                    loginResult = sendGet(login_real_url, testCase.getParams(), testCase.getHeaders());

                    try {
                        Assert.assertNotNull(loginResult, "Can not requests the interface! Nothing responded !\n");
                        Assert.assertNotEquals(loginResult, "", "Can not requests the interface! Nothing responded !\n");
                    } catch (Exception es) {
                        es.printStackTrace();
                    }
                    System.out.println(loginResult);
                } else if (testCase.getMethod().equals("POST")) {
                    loginResult = sendPost(login_real_url, testCase.getParams(), testCase.getHeaders());

                    try {
                        Assert.assertNotNull(loginResult, "Can not requests the interface! Nothing responded !\n");
                        Assert.assertNotEquals(loginResult, "", "Can not requests the interface! Nothing responded !\n");
                        loginMap.put("Response", loginResult);
                        Gson gson = new Gson();
                        Map<String, Object> map = new HashMap<>();
                        map = gson.fromJson(loginResult, map.getClass());
                        if ("200".equals(map.get("code"))) {
                            Map<?, ?> dataMap = (Map<?, ?>) map.get("data");
                            jedis.set("erp_test_token", dataMap.get("token").toString());
                        }
                        assert "200".equals(map.get("code")) : "Requests wrong !";
                    } catch (Exception es) {
                        es.printStackTrace();
                    }
                }
            }
        }

    }

    @AfterClass
    public void afterClass() {
    }

    @BeforeTest
    public void beforeTest() {
    }

    @AfterTest
    public void afterTest() {
    }

    @BeforeSuite
    public void beforeSuite() {
    }

    @AfterSuite
    public void afterSuite() {
    }


    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url   发送请求的URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    @SuppressWarnings("unchecked")
    private String sendGet(String url, String param, String header) {
        StringBuilder result = null;
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            Gson gson = new Gson();
            Map<String, Object> headerMap = new HashMap<>();
            headerMap = gson.fromJson(header, headerMap.getClass());
            String contentType = (String) headerMap.get("Content-Type");
            String token = (String) headerMap.get("token");

            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.setRequestProperty("Content-Type", contentType);
            connection.setRequestProperty("token", token);
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(10000);
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                assert false;
                result.append(line);
            }

        } catch (Exception e) {
            System.out.println("发送GET请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        assert false;
        return result.toString();
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    @SuppressWarnings("unchecked")
    private static String sendPost(String url, String param, String headers) {
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性

            Gson gson = new Gson();
            Map<String, Object> map = new HashMap<>();
            map = gson.fromJson(headers, map.getClass());
            String contentType = (String) map.get("Content-Type");

            conn.setRequestProperty("Content-Type", contentType);

            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setConnectTimeout(10000);
            conn.setReadTimeout(10000);

            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            //1.获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            //2.中文有乱码的需要将PrintWriter改为如下
            //out=new OutputStreamWriter(conn.getOutputStream(),"UTF-8")
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }


        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        System.out.println("post推送结果：" + result);
        return result.toString();
    }

    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("-?[0-9]+.?[0-9]+");
        return pattern.matcher(str).matches();
    }
}
